package com.zangs.emqx_expand.emqx.service;


import com.zangs.emqx_expand.common.constant.CacheConstants;
import com.zangs.emqx_expand.common.constant.MqttConstants;
import com.zangs.emqx_expand.common.core.domain.AjaxResult;
import com.zangs.emqx_expand.common.core.redis.RedisCache;
import com.zangs.emqx_expand.common.core.text.Convert;
import com.zangs.emqx_expand.common.exception.ServiceException;
import com.zangs.emqx_expand.emqx.domain.*;
import com.zangs.emqx_expand.emqx.mapper.MqttAclMapper;
import com.zangs.emqx_expand.emqx.mapper.MqttUserMapper;
import com.zangs.emqx_expand.emqx.mapper.MqttUserOnlineMapper;
import com.zangs.emqx_expand.emqx.mqtt.MqttConfig;
import com.zangs.emqx_expand.emqx.utils.EncryptUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class MQTTService {
    private static final Logger log = LoggerFactory.getLogger("MQTTService");

    @Resource
    private MqttConfig mqttConfig;


    @Resource
    private MqttUserMapper mqttUserMapper;
    @Resource
    private MqttUserOnlineMapper mqttUserOnlineMapper;
    @Resource
    private MqttAclMapper mqttAclMapper;
    @Autowired
    private RedisCache redisCache;
    /**
     * emqx调用登录方法
     *
     * @param emqxLoginUser emqx请求登陆的参数
     * @return 登陆结果
     */
    @Transactional(rollbackFor = {NullPointerException.class})
    public ResponseEntity<?> login(EmqxLoginUser emqxLoginUser) {
        String allowRepeatedLoginOfClientId = Convert.toStr(redisCache.getCacheObject(CacheConstants.SYS_CONFIG_KEY + "sys.allowRepeatedLoginOfClientId"));
        Map<String, Object> responseBody = new HashMap<>();
        MqttUser mqttUser;
        //判断clientid是否为空
        if (!StringUtils.hasText(emqxLoginUser.getClientid())) {
            responseBody.put("result", "ignore");
            responseBody.put("msg", "clientid不能为空");
            log.error("clientid不能为空");

            return ResponseEntity.status(HttpStatus.OK).header("Content-Type", "application/json").body(responseBody);
        }

        try {
            mqttUser = mqttUserMapper.selectMqttUserByUsername(emqxLoginUser.getUsername());
            if (ObjectUtils.isEmpty(mqttUser)) {
                //如果查找用户失败
                if (mqttConfig.getUsername().equals(emqxLoginUser.getUsername())
                        && mqttConfig.getClientId().equals(emqxLoginUser.getClientid())
                        && mqttConfig.getPassword().equals(emqxLoginUser.getPassword())
                ) {
                    responseBody.put("is_superuser", true);
                    responseBody.put("result", "allow");
                    return ResponseEntity.status(HttpStatus.OK).header("Content-Type", "application/json").body(responseBody);

                }
                throw new NullPointerException("查找用户失败");
            }
            //校验密码是否匹配
            if (EncryptUtils.sha256(emqxLoginUser.getPassword(), mqttUser.getSalt()).equals(mqttUser.getPassword())) {
                //如果是管理员或系统允许重复登陆
                if (mqttUser.getIsSuperuser() ) {
                    responseBody.put("is_superuser", true);
                }
                else if (!Convert.toBool(allowRepeatedLoginOfClientId,true)){
                    //查询是否已经存在此clientid的在线记录
                    MqttUserOnline mqttUserOnline = mqttUserOnlineMapper.selectMqttUserOnlineByUserIdAndClientId(mqttUser.getId(), emqxLoginUser.getClientid());
                    if (ObjectUtils.isEmpty(mqttUserOnline)) {
                        log.error("不存在此clientid的在线记录");

                        throw new NullPointerException("不存在此clientid的在线记录");

                    }
                    //更新在线记录信息
                    mqttUserOnline.setOnline(true);
                    mqttUserOnlineMapper.updateMqttUserOnline(mqttUserOnline);
                    log.error("更新在线记录信息成功");

                }
                responseBody.put("result", "allow");
                log.info("登陆成功");

                //返回登陆成功的消息
                return ResponseEntity.status(HttpStatus.OK).header("Content-Type", "application/json").body(responseBody);

            }

            //密码错误拒绝
            responseBody.put("result", "deny");
            log.error("密码错误拒绝");

            return ResponseEntity.status(HttpStatus.OK).
                    header("Content-Type", "application/json").body(responseBody);
        } catch (NullPointerException e) {
            log.error("查询不到用户的跳过");

            //查询不到用户的跳过
            responseBody.put("result", "ignore");
            return ResponseEntity.status(HttpStatus.OK).
                    header("Content-Type", "application/json").body(responseBody);
        }
    }


    public AjaxResult addUser(MqttUser mqttUser) {

            mqttUser.setPassword(EncryptUtils.sha256(mqttUser.getPassword(), mqttUser.getSalt()));

        try {
            mqttUserMapper.insertMqttUser(mqttUser);
            return AjaxResult.success(mqttUser);
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error("插入数据失败");
        }
    }

    public boolean hasAcl(EmqxAcl emqxAcl) {
        /**
         * 管理员一律允许，普通用户没有的一律拒绝
         */
        MqttUser byUsername = mqttUserMapper.selectMqttUserByUsername(emqxAcl.getUsername());
        if (ObjectUtils.isEmpty(byUsername)) {
            //如果是本机的账号就给予权限否则不赋予权限
            return mqttConfig.getUsername().equals(emqxAcl.getUsername());
        }
        if (byUsername.getIsSuperuser()) {
            //如果是管理员就给予权限
            return true;
        }
        //如果是告警通知就赋予推送消息的权限（谁都可以推送）
        if (emqxAcl.getAction().equals(MqttConstants.ACTION_PUBLISH) && Pattern.compile("^" + MqttConstants.ALARM + "/([^/]+)/([^/]+)/([^/]+)$").matcher(emqxAcl.getTopic()).matches()) {
            System.out.println("匹配成功");
            String[] parts = emqxAcl.getTopic().split("/");
            if (parts[1].equals(emqxAcl.getUsername()) &&
                    parts[2].equals(emqxAcl.getClientid())) {
                return true;
            }
        }

        List<MqttAcl> allByUserId = mqttAclMapper.selectMqttAclByUserIdAndTopic(byUsername.getId(), emqxAcl.getTopic());
        boolean hasAcl = false;
        int len = 0;
        for (MqttAcl mqttAcl : allByUserId) {
            if (MqttConstants.ACTION_ALL.equals(mqttAcl.getAction()) || mqttAcl.getAction().equals(emqxAcl.getAction())) {
                if ((StringUtils.hasText(emqxAcl.getClientid()) && !StringUtils.hasText(mqttAcl.getClientId())) ||
                        (StringUtils.hasText(emqxAcl.getPeerhost()) && !StringUtils.hasText(mqttAcl.getIpAddress()))) {
                    continue;
                }
                if (matches(emqxAcl.getTopic(), mqttAcl.getTopic())) {
                    log.info(emqxAcl.getTopic() + " - " + mqttAcl.getTopic());
                    if (len < mqttAcl.getTopic().length()) {
                        hasAcl = mqttAcl.getPermission();
                        len = mqttAcl.getTopic().length();
                    }
                }
            }
        }
        return hasAcl;
    }


    @Transactional
    public AjaxResult deleteUser(String[] userUids) {
        //后面修改为批量操作
        for (String userUid : userUids) {
            MqttUser mqttUser = mqttUserMapper.selectMqttUserByUidAndIsSuperuser(userUid, false);
            if (ObjectUtils.isEmpty(mqttUser)) {
                return AjaxResult.error("uid查找失败");
            }
            //删除在线记录
            mqttUserOnlineMapper.deleteByUserId(mqttUser.getId());
            //删除规则表
            mqttAclMapper.deleteByUserId(mqttUser.getId());
            //删除用户
            mqttUserMapper.deleteMqttUserById(mqttUser.getId());
        }
        return AjaxResult.success(userUids.length);

    }

    public AjaxResult editUser(MqttUser mqttUser) {
        if (!StringUtils.hasText(mqttUser.getUserUid())) {
            return AjaxResult.error("UserUid不能为空");

        }

        MqttUser queryRes = mqttUserMapper.selectMqttUserByUidAndIsSuperuser(mqttUser.getUserUid(), false);

        if (ObjectUtils.isEmpty(queryRes)) {
            return AjaxResult.error("用户查询失败");
        }
        if (!StringUtils.hasText(mqttUser.getPassword()) && StringUtils.hasText(mqttUser.getSalt())) {
            return AjaxResult.error("修改盐时必须修改密码");

        }


        if (StringUtils.hasText(mqttUser.getPassword())) {
            String salt;
            // 如果提供了盐，使用提供的盐；否则，从数据库中获取当前用户的盐
            if (StringUtils.hasText(mqttUser.getSalt())) {
                salt = mqttUser.getSalt();
            } else {

                salt = queryRes.getSalt();
            }
            queryRes.setPassword(EncryptUtils.sha256(mqttUser.getPassword(), salt));
        }
        if (StringUtils.hasText(mqttUser.getUsername())) {
            queryRes.setUsername(mqttUser.getUsername());
        }

        return AjaxResult.success(mqttUserMapper.updateMqttUser(queryRes));
    }


    public static boolean matches(String topic, String pattern) {
        String[] topicLevels = topic.split("/");
        String[] patternLevels = pattern.split("/");
        int topicIndex = 0;
        int patternIndex = 0;
        while (patternIndex < patternLevels.length) {
            String patternLevel = patternLevels[patternIndex];
            if ("#".equals(patternLevel)) {
                return true;
            } else if ("+".equals(patternLevel)) {
                if (topicIndex >= topicLevels.length) {
                    return false;
                }
                topicIndex++;
            } else {
                if (topicIndex >= topicLevels.length || !patternLevel.equals(topicLevels[topicIndex])) {
                    return false;
                }
                topicIndex++;
            }
            patternIndex++;
        }

        return topicIndex == topicLevels.length;
    }

    public static void main(String[] args) {


        if (Pattern.compile("^alarm/([^/]+)/([^/]+)/([^/]+)$").matcher("alarm/aa/bb/ccc").matches()) {
            System.out.println("匹配成功");
            String[] parts = "alarm/aa/bb/ccc".split("/");

        }


        System.out.println(EncryptUtils.sha256("test", "salt").equals("4edf07edc95b2fdcbcaf2378fd12d8ac212c2aa6e326c59c3e629be3039d6432")
        );
        System.out.println(matches("a/b/c/c/c", "#"));       // true
        System.out.println(matches("a/b/c", "a/b/+"));     // true
        System.out.println(matches("a/b/c/d", "a/b/+"));   // false
        System.out.println(matches("a/b/x", "a/b/+"));     // true
        System.out.println(matches("a/x/c", "a/b/+"));     // false
    }

    public int deleteAllBy(String[] clientIds) {
        return mqttAclMapper.deleteByClientIds(clientIds);
    }

    @Transactional
    public AjaxResult addAcl(String userUid, List<MqttAcl> mqttAcl) {

        MqttUser byUsernameAndIsSuperuser = mqttUserMapper.selectMqttUserByUidAndIsSuperuser(userUid, false);
        if (!ObjectUtils.isEmpty(byUsernameAndIsSuperuser)) {

            for (MqttAcl acl : mqttAcl) {
                acl.setUserId(byUsernameAndIsSuperuser.getId());
                try {
                    mqttAclMapper.insertMqttAcl(acl);
                } catch (Exception e) {
                    log.error(e.getMessage());
                    return AjaxResult.error("插入数据失败" + acl.toString());
                }
            }

            return AjaxResult.success("添加规则成功");

        }
        return AjaxResult.error("用户查询失败");
    }


    public AjaxResult editAclTopicByUid(String topicUid, String topic) {
        MqttAcl query = new MqttAcl();
        query.setTopicUid(topicUid);

        List<MqttAcl> byUid = mqttAclMapper.selectMqttAclList(query);

        for (MqttAcl item : byUid) {
            item.setTopic(topic);
            try {
                mqttAclMapper.updateMqttAcl(item);
            } catch (Exception e) {
                return AjaxResult.error("保存失败");
            }
        }
        return AjaxResult.success("保存成功");
    }


    @Transactional
    public int editAclByPrefix(String prefix, String newPrefix) {
        return mqttAclMapper.updatePrefix(prefix, newPrefix);
    }

    @Transactional
    public int addUserStatus(List<MqttUserOnline> mqttUserOnline) {
        // 提取所有 userUid
        List<String> userUids = mqttUserOnline.stream()
                .map(MqttUserOnline::getUserUid)
                .collect(Collectors.toList());

        // 批量查询 MqttUser
        List<MqttUser> mqttUsers = mqttUserMapper.selectMqttUsersByUidsAndIsSuperuser(userUids, false);

        // 构建 userUid -> userId 的映射
        Map<String, Long> userUidToIdMap = mqttUsers.stream()
                .collect(Collectors.toMap(MqttUser::getUserUid, MqttUser::getId));

        // 设置 userId
        for (MqttUserOnline online : mqttUserOnline) {
            Long userId = userUidToIdMap.get(online.getUserUid());
            if (userId != null) {
                online.setUserId(userId);
            } else {
                throw new ServiceException("User not found for UID: " + online.getUserUid());
            }
        }

        return mqttUserOnlineMapper.insertMqttUserOnlines(mqttUserOnline);
    }

    public int deleteMqttUserOnline(String userUid, String[] clientIds) {
        return mqttUserOnlineMapper.deleteMqttUserOnlineByUserUidAndClientIds(userUid, clientIds);
    }

    @Transactional
    public AjaxResult editUserStatusClientId(List<MqttUserOnline> mqttUserOnlineList) {

        for (MqttUserOnline mqttUserOnline : mqttUserOnlineList) {
            if (!StringUtils.hasText(mqttUserOnline.getDeviceUid())) {
                return AjaxResult.error("DeviceUid不能为空");
            }
            MqttUserOnline byUid = mqttUserOnlineMapper.selectMqttUserOnlineByDeviceUid(mqttUserOnline.getDeviceUid());
            if (!ObjectUtils.isEmpty(byUid)) {
                if (!ObjectUtils.isEmpty(byUid.getOnline())) {
                    byUid.setOnline(mqttUserOnline.getOnline());
                }

                if (StringUtils.hasText(byUid.getClientId())) {
                    byUid.setClientId(mqttUserOnline.getClientId());
                }
                mqttUserOnlineMapper.updateMqttUserOnline(byUid);
            } else {
                return AjaxResult.error("没有该uid数据");

            }
        }

        return AjaxResult.success("修改成功");
    }
}
